package net.qhzw.vip.qiyu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.qhzw.vip.qiyu.component.JwtTokenTemplate;
import net.qhzw.vip.qiyu.entity.DtsUser;
import net.qhzw.vip.qiyu.handler.ApiException;
import net.qhzw.vip.qiyu.handler.MyException;
import net.qhzw.vip.qiyu.mapper.DtsUserMapper;
import net.qhzw.vip.qiyu.model.*;
import net.qhzw.vip.qiyu.result.PageResult;
import net.qhzw.vip.qiyu.service.DtsUserService;
import net.qhzw.vip.qiyu.service.SysCommunityService;
import net.qhzw.vip.qiyu.service.SysUserService;
import net.qhzw.vip.qiyu.util.PageAdapter;
import net.qhzw.vip.qiyu.util.RedisUtils;
import net.qhzw.vip.qiyu.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class DtsUserServiceImpl extends ServiceImpl<DtsUserMapper, DtsUser>
        implements DtsUserService {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysCommunityService communityService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private JwtTokenTemplate jwtTokenTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private DtsUserMapper dtsUserMapper;

    /***
     * 分页查询用户
     * @param page
     * @param dtsUser
     * @return
     */
    @Override
    public Page<DtsUser> findByPage(Page<DtsUser> page, DtsUser dtsUser) {
        page.addOrder(OrderItem.desc("auth_time"));
        Page<DtsUser> userPage = page(page, new LambdaQueryWrapper<DtsUser>()
                .like(dtsUser != null && !StringUtils.isEmpty(dtsUser.getUsername()), DtsUser::getUsername, dtsUser.getUsername())
                .eq(dtsUser != null && !StringUtils.isEmpty(dtsUser.getMobile()), DtsUser::getMobile, dtsUser.getMobile())
                .eq(dtsUser != null && !StringUtils.isEmpty(dtsUser.getUserLevel()), DtsUser::getUserLevel, dtsUser.getUserLevel())
                .eq(dtsUser != null && !StringUtils.isEmpty(dtsUser.getAuthStatus()), DtsUser::getAuthStatus, dtsUser.getAuthStatus())
        );
        return userPage;
    }

    /***
     * 站点管理员登录
     * @param username
     * @param password
     * @return
     */
    @Override
    public LoginUser login(String username, String password) {
        return null;
    }

    /*public LoginUser login(String username, String password) {
        JwtToken jwtToken = null;
        try {
            jwtToken = jwtTokenTemplate.sendLogin(new LoginForm("frontdesk_type", username, password, null),
                    restTemplate);
            log.info("远程调用成功,结果为", JSON.toJSONString(jwtToken, true));
            if (StringUtils.isEmpty(jwtToken)) {
                throw new MyException(500, "用户名或密码错误");
            }
            //查询菜单数据
//            Jwt jwt = JwtHelper.decode(jwtToken.getAccessToken());
//            String jwtJsonStr = jwt.getClaims();
            String jwtJsonStr = "";
            JSONObject jtwJson = JSON.parseObject(jwtJsonStr);
            //根据jwt数据获取用户id
            Long userId = Long.valueOf(jtwJson.getString("user_name"));
            LoginUser loginUser = new LoginUser(username,
                    String.valueOf(userId),
                    jwtToken.getExpiresIn(),
                    jwtToken.getTokenType() + " " + jwtToken.getAccessToken(),
                    jwtToken.getRefreshToken());
            log.info("微信登录成功, 结果为:【{}】", JSON.toJSONString(loginUser, true));
            return loginUser;
        } catch (Exception e) {
            throw new MyException(500, "用户名或密码错误");
        }
    }*/

    /***
     * 用户认证
     * @param userId
     * @param userAuthForm
     * @return
     */
    @Override
    public boolean identifyVerify(Long userId, UserAuthForm userAuthForm) {
        @NotBlank String idCard = userAuthForm.getIdCard();
        int count = count(new LambdaQueryWrapper<DtsUser>()
                .eq(DtsUser::getIdCard, idCard)
                .eq(DtsUser::getAuthStatus, 2));
        if (count > 0) {
            throw new ApiException(userAuthForm.getRealName() + "您已有认证的账号, 请联系管理员删除之前的账号!");
        }
        DtsUser dtsUser = getById(userId);
        if (dtsUser == null) {
            throw new MyException(500, "获取不到用户信息,请重新登录");
        }
        //获取用户手机验证码
        String verificationCd = stringRedisTemplate.opsForValue().get("SMS:FORGOT_VERIFY:" + userAuthForm.getMobile());
        if (StringUtils.isEmpty(verificationCd)) {
            throw new MyException(500, "验证码已过期,请重新发送");
        }
        if (!verificationCd.equals(userAuthForm.getCode())) {
            throw new MyException(500, "验证码错误");
        }
        dtsUser.setAuthStatus((byte) 1);
        dtsUser.setAuthTime(new Date());
        dtsUser.setRealName(userAuthForm.getRealName());
        dtsUser.setIdCard(userAuthForm.getIdCard().toUpperCase());
        dtsUser.setFrontPhoto(userAuthForm.getFrontPhoto());
        dtsUser.setHoldingPhoto(userAuthForm.getHoldingPhoto());
        dtsUser.setReversePhoto(userAuthForm.getReversePhoto());
        dtsUser.setMobile(userAuthForm.getMobile());
        dtsUser.setBatteryId(userAuthForm.getBatteryId());
        dtsUser.setBatteryType(userAuthForm.getBatteryType());
        dtsUser.setEmergencyContact(userAuthForm.getEmergencyContact());
        return updateById(dtsUser);
    }

    /***
     * 添加用户
     * @param dtsUser
     * @return
     */
    @Override
    public boolean addDtsUser(DtsUser dtsUser) {
        checkAdd(dtsUser);
        dtsUser.setId(IdWorker.getId());
        dtsUser.setPassword(new BCryptPasswordEncoder().encode(dtsUser.getPassword()));
        dtsUser.setUserLevel((byte) 1);
        dtsUser.setStatus((byte) 1);
        dtsUser.setModifyBy(SecurityUtils.getUserId());
        dtsUser.setUserRegtime(new Date());
        dtsUser.setUsername(dtsUser.getMobile());
        return save(dtsUser);
    }

    /***
     * 新增前校验参数
     * @param dtsUser
     */
    private void checkAdd(DtsUser dtsUser) {
        int count = count(new LambdaQueryWrapper<DtsUser>()
                .eq(DtsUser::getUserLevel, 1)
                .eq(DtsUser::getMobile, dtsUser.getMobile())
        );
        if (count > 0) {
            throw new MyException(500, "该手机已存在,请更换手机号");
        }
    }

    /***
     * 修改用户
     * @param dtsUser
     * @return
     */
    @Override
    public boolean updateDtsUser(DtsUser dtsUser) {
        dtsUser.setModifyBy(SecurityUtils.getUserId());
        dtsUser.setModifyTime(new Date());
        boolean update = updateById(dtsUser);
        if (update) {
            checkUpdate(dtsUser);
            return true;
        }
        return false;
    }


    /***
     * 修改后参数校验
     * @param dtsUser
     */
    private void checkUpdate(DtsUser dtsUser) {
        int count = count(new LambdaQueryWrapper<DtsUser>()
                .eq(DtsUser::getUserLevel, 1)
                .eq(DtsUser::getMobile, dtsUser.getMobile())
        );
        if (count > 1) {
            throw new MyException(500, "该手机已存在,请更换手机号");
        }
    }

    /***
     * 审核实名认证
     * @param verifiedForm
     * @return
     */
    @Override
    public boolean verified(VerifiedForm verifiedForm) {
        DtsUser dtsUser = new DtsUser();
        dtsUser.setId(verifiedForm.getId());
        dtsUser.setAuthStatus(verifiedForm.getStatus());
        dtsUser.setAuditRsults(verifiedForm.getAuditRsults());
        dtsUser.setModifyBy(SecurityUtils.getUserId());
        dtsUser.setModifyTime(new Date());
        return updateById(dtsUser);
    }

    /***
     * 根据社区id查询社区名称
     * @param communityId
     * @return
     */
    @Override
    public String getCommunityNameById(Long communityId) {
        return communityService.getCommunityNameById(communityId);
    }

    /***
     * 根据关键词查询用户
     * @param keywords
     * @return
     */
    @Override
    public List<DtsUser> findListByKeywords(String keywords) {
        List<DtsUser> list = list(new LambdaQueryWrapper<DtsUser>()
                .eq(DtsUser::getUserLevel, 0)
                .like(DtsUser::getRealName, keywords)
                .or()
                .eq(DtsUser::getMobile, keywords)
                .or()
                .eq(DtsUser::getIdCard, keywords)
        );
        return list;
    }

    @Autowired
    private RedisUtils redisUtils;

    /***
     * 修改用户信息
     * @param param
     * @return
     */
    @Override
    public boolean modifyUsrInfo(ModifyUsrInfoParam param) {
        //参数校验
        cheacker(param);
        DtsUser dtsUser = new DtsUser();
        dtsUser.setBatteryId(param.getBatteryId());
        dtsUser.setBatteryType(param.getBatteryType());
        dtsUser.setEmergencyContact(param.getEmergencyContact());
        dtsUser.setMobile(param.getMobile());
        dtsUser.setId(SecurityUtils.getUserId());
        return updateById(dtsUser);
    }

    /***
     * 查询结余欠款
     * @return
     */
    @Override
    public String balanceArrears(Long shopId) {
        return dtsUserMapper.balanceArrears(shopId);
    }

    /***
     * 根据站点ID查询管理员手机号
     * @return
     */
    @Override
    public List<String> getMobileByCommunityId(Long communityId) {
        return dtsUserMapper.getMobileByCommunityId(communityId);
    }

    @Override
    public DtsUser getUserByUsername(String username) {
        List<DtsUser> list = list(new LambdaQueryWrapper<DtsUser>()
                .eq(DtsUser::getUsername, username)
        );
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 获取站点维修人员
     *
     * @param communityId
     * @return
     */
    @Override
    public List<DtsUser> getDtsUser(Long communityId) {
        return dtsUserMapper.getMaintDtsUser(communityId);
    }

    /**
     * 用户余额清零
     *
     * @param userId
     */
    @Override
    public void clearTheBal(Long userId) {
        dtsUserMapper.clearTheBal(userId);
    }

    @Override
    public PageResult<DtsUser> findAauthPage(PageAdapter pageAdapter, String realName, String idCard, String mobile, Byte authStatus, Long shopId) {
        List<DtsUser> userList = new ArrayList<>();
        Long total = 0L;
        if (shopId == 1) {
            userList = dtsUserMapper.findAauthPage(pageAdapter, realName, idCard, mobile, authStatus);
            total = dtsUserMapper.findAauthPageTotal(realName, idCard, mobile, authStatus);
            //userList = list();

        }
        return new PageResult<DtsUser>(total, userList);
    }

    /**
     * 租车用户信息查询
     *
     * @param page
     * @param shopId
     * @param realName
     * @param mobile
     * @param idCard
     * @return
     */
    @Override
    public PageResult<DtsUser> findCarRental(Page<DtsUser> page, Long shopId, String realName, String mobile, String idCard) {
        List<DtsUser> userList = dtsUserMapper.findCarRental(new PageAdapter(page), shopId, realName, mobile, idCard);
        Long total = dtsUserMapper.findCarRentalCount(shopId, realName, mobile, idCard);
        return new PageResult<DtsUser>(total, userList);
    }

    /**
     * 商城用户
     *
     * @param page
     * @param name
     * @return
     */
    @Override
    public PageResult<DtsUser> findMall(Page<DtsUser> page, String name, Byte isVip) {
        page.addOrder(OrderItem.desc("user_regtime"));
        Page<DtsUser> dtsUserPage = page(page, new LambdaQueryWrapper<DtsUser>()
                .eq(DtsUser::getUserLevel, 0)
                .eq(isVip != null, DtsUser::getMallVip, isVip)
                .and(!StringUtils.isEmpty(name), wq -> wq
                        .like(DtsUser::getNickname, name)
                        .or()
                        .eq(DtsUser::getMobile, name)
                        .or()
                        .like(DtsUser::getRealName, name)));
        return new PageResult<DtsUser>(dtsUserPage.getTotal(), dtsUserPage.getRecords());
    }

    @Override
    public int getUserStatus(Long userId) {
        return dtsUserMapper.getUserStatus(userId);
    }

    /***
     *  参数校验
     * @param param
     */
    private void cheacker(ModifyUsrInfoParam param) {
        Integer count = redisUtils.getCacheObject("modifyUser:" + SecurityUtils.getUserId());
        count = count == null ? 1 : count;
        if (10 < count) {
            throw new MyException("今日修改次数上限,请明日在修改!");
        }
        redisUtils.setCacheObject("modifyUser:" + SecurityUtils.getUserId(), count + 1, 1, TimeUnit.DAYS);

        //获取用户手机验证码
        String verificationCd = stringRedisTemplate.opsForValue().get("SMS:FORGOT_VERIFY:" + param.getMobile());
        if (StringUtils.isEmpty(verificationCd)) {
            throw new MyException(500, "验证码已过期,请重新发送");
        }
        if (!verificationCd.equals(param.getCode())) {
            throw new MyException(500, "验证码错误");
        }

    }

}
